/**
 * 联合类型和类型保护
 * 当前变量不确定是一个类型的时候，比如 const abc: string|number 变量值有可能是字符串或是数字
 * 类型保护，当联合类型的变量不确定类型的时候，执行的时候 需要避免出现 string+number 这种情况出现
 * 常用的类型保护方法 in (针对比较固定的接口，类，方法)，typeof（针对变量类型），instanceof（针对是否又某个类创建的对象）
 **/

//联合类型示例 x,y 的值不能确定是字符串还是数字 - 这种判断变量类型的可以用 typeof 来对联合类型数据进行 类型守护
function add1(x: string | number, y: string | number) {
    //联合类型的，需要做类型保护，否则就会像下面这个语句就会报错
    //return x + y;
    //类型守护 - 用typeof判断类型
    if (typeof (x) === 'string' && typeof (y) === 'string') {
        return `${x}${y}`;
    }
    if (typeof (x) === 'number' && typeof (y) === 'number') {
        return x + y;
    }
}


//这种联合类型的参数是类的情况下，对是否包含某个方法 可以 in 的方式来做类型守护
class A22 {
    sayHello() {
        console.log('hello');
    }
}
class A23 {
    sayBye() {
        console.log('bye');
    }
}

function A24(wh: A22 | A23) {
    //下面语句报错是因为当前方法的参数 wh 是个联合类型，无法确定是哪个类
    // wh.sayHello();
    //面对这种情况可以使用 in 来做类型保护 判断这个联合类型 wh 是否有某个方法
    if ('sayHello' in wh) {
        wh.sayHello();
    } else {
        wh.sayBye();
    }
}

//还有一种联合类型，类型守护可以用 instanceof 判断是否是由某个类生成的
class NumObj {
    my_score!: number; //这个!: 的这个叹号的作用是 my_score 必须是个非null和undefined的值，否则会报错
}

function add(x:object|NumObj,y:object|NumObj){
    //直接输出 会报错，需要做类型保护
    // return x.my_score + y.my_score;
    // 判断是否是类的类型守护 可以用 instanceof
    if(x instanceof NumObj && y instanceof NumObj){
        return x.my_score + y.my_score;
    }
}